package ssh;

import java.io.IOException;
import java.io.InputStream;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import model.IPAddress;
import utils.IllegalValueException;


public class SSHConnectionHandlerFake {

	private static final Logger log = Logger.getLogger(SSHConnectionHandlerFake.class);
	
	private Session session;
	private Channel channel;
	private String output;
	
	/**
	 * Crea un gestore per una singola connessione ssh2
	 * 
	 * @param conn
	 */
	public SSHConnectionHandlerFake(Session session) 
	{
		this.session = session;
		this.channel = null;
		this.output = "";
	}

	/**
	 * Invia un comando sulla connessione ssh2. Il risultato del comando, in
	 * termini di risposta della connessione ssh, viene riportato in stdOut ed in
	 * stdErr.
	 * 
	 * Qualora il comando eseguito non dovesse terminare con valore di ritorno
	 * 0, viene lanciata una eccezione.
	 * 
	 * @param command
	 * @throws SSHCommandException
	 */
	public int sendCommand(String command) {

		try{
		
			output = "";
			
			channel = session.openChannel("exec");
			((ChannelExec)channel).setCommand(command);
	
			
		    channel.setInputStream(null);
		    ((ChannelExec)channel).setErrStream(System.err);
	
		    InputStream in=channel.getInputStream();
	
		    channel.connect();
	
		    byte[] tmp=new byte[1024];
		    while(true){
		    	
		    	while(in.available()>0){
		    		int i=in.read(tmp, 0, 1024);
		    		if(i<0)break;
		    		output = new String(tmp, 0, i);
		    	}
		    	if(channel.isClosed()){
		    		return channel.getExitStatus();
		    	}
		    }
		    
		}catch(Exception e){
			System.out.println(e);
	    }
		return -1;
		
	}
	
	public String getOutput(){
		return output;
	}
	
	/**
	 * Invia un comando sulla connessione ssh2. Il risultasto del comando, in
	 * termini di risposta della connessione ssh, viene riportato nello stdOut,
	 * che puo' essere letto dopo aver eseguito il comando.
	 * 
	 * Il valore di ritorno con cui termina il comando viene restituito dal
	 * metodo. Questa metodo puo' essere usato per eseguire quei comandi la cui
	 * mancata terminazione con 0 non e' considerata un'eccezione.
	 * 
	 * @param command
	 * @throws IOException
	 * @throws SSHCommandException
	 */
	public void sendCommandNoErrorControl(String command) throws SSHCommandException {
		
	}	

	/**
	 * Chiude la connessione ssh2 legata a questo gestore
	 */
	public void dispose() {
		
		channel.disconnect();
		session.disconnect();

		log.info("Disconnected");
	}

	public static SSHConnectionHandlerFake createSSHConnectionHandler(IPAddress ipAddress, 
							int port, String username, String password) throws JSchException{

		log.info("Try to connect to " + ipAddress.getAddress() + ":" + port + "...");
					
			JSch jsch = new JSch();
			Session session = jsch.getSession(username, ipAddress.getAddress(), port);
			session.setPassword(password);
			session.setConfig("StrictHostKeyChecking", "no");
			session.connect();
			
			log.info("... connected to " + ipAddress.getAddress() + ":" + port);
			
			return new SSHConnectionHandlerFake(session);
		
	}
	
	public static void main(String[] args) throws JSchException
	{	
		IPAddress ipAddres;
		try {
			
			ipAddres = new IPAddress(4,"192.168.74.16","255.255.255.0");
			SSHConnectionHandlerFake handler = SSHConnectionHandlerFake.createSSHConnectionHandler(ipAddres,22, "root","nepadmpwd");
			System.out.print("ExitCode: " + handler.sendCommand("tc qdisc show") + "\n");
			System.out.print("ExitCode: " + handler.sendCommand("ebtables -L") + "\n");
			System.out.println("Output: " + handler.getOutput());
			handler.dispose();
			
		} catch (IllegalValueException e) {
			e.printStackTrace();
		}
		
	}
	
}
